package io.finer.erp.jeecg.bas.service.impl;

import java.math.BigDecimal;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.transaction.Transactional;

import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.oConvertUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.api.client.util.Maps;
import com.google.common.collect.Lists;

import cn.hutool.core.lang.UUID;
import io.finer.erp.jeecg.bas.dto.InventoryDTO;
import io.finer.erp.jeecg.bas.dto.MaterialContrastDTO;
import io.finer.erp.jeecg.bas.entity.BasMaterial;
import io.finer.erp.jeecg.bas.entity.BasMaterialLog;
import io.finer.erp.jeecg.bas.mapper.BasMaterialLogMapper;
import io.finer.erp.jeecg.bas.service.IBasMaterialLogService;
import io.finer.erp.jeecg.bas.service.IBasMaterialService;
import io.finer.erp.jeecg.bas.vo.BasMaterialLogVO;
import io.finer.erp.jeecg.stock.entity.StkInventory;
import io.finer.erp.jeecg.stock.entity.StkTrayDetail;
import io.finer.erp.jeecg.stock.mapper.StkTrayDetailMapper;
import io.finer.erp.jeecg.stock.service.IStkInventoryService;
import io.finer.erp.jeecg.stock.util.ScanUtil;

/**
 * @Description: PDA物料盘点记录
 * @Author: jeecg-boot
 * @Date:   2021-05-11
 * @Version: V1.0
 */
@Service
public class BasMaterialLogServiceImpl extends ServiceImpl<BasMaterialLogMapper, BasMaterialLog> implements IBasMaterialLogService {

	@Autowired
	private BasMaterialLogMapper materialLogMapper;
	@Autowired
	private IBasMaterialService basMaterialService;
	@Autowired
	private StkTrayDetailMapper stkTrayDetailMapper;
	@Autowired
	private IStkInventoryService stkInventoryService;
	@Autowired
	private IBasMaterialService materialService;

	@Override
	@Transactional
	public Result<?> addMaterialLog(List<String> codeList, String sheetId) {
		// TODO Auto-generated method stub
		if(codeList==null || codeList.size()==0) {
			return Result.error("PDA未扫入物料码或托盘码");
		}
		if(oConvertUtils.isEmpty(sheetId)) {
			return Result.error("未选盘点单，请选盘点单");
		}
		LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
		String user = "";
		if(sysUser!=null) {
			user = sysUser.getUsername();
		}
		//code物料编号或托盘码，根据code查询是托盘码，还是物料编码
		List<String> materialCode = Lists.newArrayList();
		List<String> trayCodes = Lists.newArrayList();
		for(String code:codeList) {
			boolean isTrayCode = ScanUtil.isTrayCode(code);
			if(isTrayCode) {
				trayCodes.add(code);
			}else {
				materialCode.add(code);
			}
		}
		//查询记录表里所有物料编号，筛选重复记录数据
		StringBuffer buffer = new StringBuffer();
		if(materialCode!=null&&materialCode.size()>0) {
			List<String> logCodeList = baseMapper.selectMaterialCodeList();
			//记录录入物料，返回已重复记录过物料编码
			List<BasMaterial> basMaterialList = basMaterialService.getByCodes(materialCode);
			List<BasMaterialLog> logList = Lists.newArrayList();
			BigDecimal quantity = BigDecimal.ZERO;
			String remark = "";
			String supplier = "";
			String model = "";
			if(basMaterialList!=null&&basMaterialList.size()>0) {
				for(BasMaterial basMaterial:basMaterialList) {
					StkInventory stk = stkInventoryService.getByMaterial(basMaterial.getId());
					if(stk!=null) {
						quantity = stk.getQty();
						remark = stk.getRemark();
						supplier = stk.getSupplierId();
						model = stk.getModel();
					}else {
						throw new RuntimeException("物料编号为："+ basMaterial.getCode() +"的物料不在库存中");
					}
					if(logCodeList.contains(basMaterial.getCode())) {
						buffer.append(basMaterial.getCode());
						buffer.append(",");
					}else {
						BasMaterialLog basMaterialLog = new BasMaterialLog();
						basMaterialLog.setSheetId(sheetId);
						basMaterialLog.setCategoryId(basMaterial.getCategoryId());
						basMaterialLog.setCode(basMaterial.getCode());
						basMaterialLog.setCodeImg(basMaterial.getCodeImg());
						basMaterialLog.setCreateBy(user);
						basMaterialLog.setCreateTime(new Date());
						basMaterialLog.setCustomerId(basMaterial.getCustomerId());
						basMaterialLog.setFormulaId(basMaterial.getFormulaId());
						basMaterialLog.setLength(basMaterial.getLength());
						basMaterialLog.setMaterialId(basMaterial.getId());
						basMaterialLog.setModel(model);
						basMaterialLog.setName(basMaterial.getName());
						basMaterialLog.setPid(basMaterial.getPid());
						basMaterialLog.setQuantity(quantity);
						basMaterialLog.setSalePrice(basMaterial.getSalePrice());
						basMaterialLog.setSquare(basMaterial.getSquare());
						basMaterialLog.setSupplier(supplier);
						basMaterialLog.setTaxCode(basMaterial.getTaxCode());
						basMaterialLog.setUnitId(basMaterial.getUnitId());
						basMaterialLog.setUpdateBy(basMaterial.getUpdateBy());
						basMaterialLog.setUpdateTime(basMaterial.getUpdateTime());
						basMaterialLog.setViceQuantity(basMaterial.getViceQuantity());
						basMaterialLog.setWidth(basMaterial.getWidth());
						basMaterialLog.setRemark(remark);
						logList.add(basMaterialLog);
					}
				}
				this.saveBatch(logList);
			}else {
				throw new RuntimeException("未查找到物料信息");
			}
		}
		if(trayCodes!=null&&trayCodes.size()>0) {
			List<String> logCodeList = baseMapper.selectMaterialCodeList();
			List<StkTrayDetail> stkTrayDetailList = stkTrayDetailMapper.selectByMainCodeList(trayCodes);
			List<String> materialCodes = Lists.newArrayList();
			Map<String,String> map = Maps.newHashMap();
			if(stkTrayDetailList!=null&&stkTrayDetailList.size()>0) {
				for(StkTrayDetail stkTrayDetail:stkTrayDetailList) {
					materialCodes.add(stkTrayDetail.getMaterialCode());
					map.put(stkTrayDetail.getMaterialCode(), stkTrayDetail.getTrayCode());
				}
				//记录录入物料，返回已重复记录过物料编码
				List<BasMaterial> basMaterialList = basMaterialService.getByCodes(materialCodes);
				List<BasMaterialLog> logList = Lists.newArrayList();
				BigDecimal quantity = BigDecimal.ZERO;
				String remark = "";
				String supplier = "";
				String model = "";
				if(basMaterialList!=null&&basMaterialList.size()>0) {
					for(BasMaterial basMaterial:basMaterialList) {
						StkInventory stk = stkInventoryService.getByMaterial(basMaterial.getId());
						if(stk!=null) {
							quantity = stk.getQty();
							remark = stk.getRemark();
							supplier = stk.getSupplierId();
							model = stk.getModel();
						}else {
							throw new RuntimeException("物料编号为："+ basMaterial.getCode() +"的物料不在库存中");
						}
						if(logCodeList.contains(basMaterial.getCode())) {
							buffer.append("托盘码为：");
							buffer.append(map.get(basMaterial.getCode()));
							buffer.append("的物料为："+basMaterial.getCode());
							buffer.append(",");
						}else {
							BasMaterialLog basMaterialLog = new BasMaterialLog();
							basMaterialLog.setSheetId(sheetId);
							basMaterialLog.setCategoryId(basMaterial.getCategoryId());
							basMaterialLog.setCode(basMaterial.getCode());
							basMaterialLog.setCodeImg(basMaterial.getCodeImg());
							basMaterialLog.setCreateBy(user);
							basMaterialLog.setCreateTime(new Date());
							basMaterialLog.setCustomerId(basMaterial.getCustomerId());
							basMaterialLog.setFormulaId(basMaterial.getFormulaId());
							basMaterialLog.setLength(basMaterial.getLength());
							basMaterialLog.setMaterialId(basMaterial.getId());
							basMaterialLog.setModel(model);
							basMaterialLog.setName(basMaterial.getName());
							basMaterialLog.setPid(basMaterial.getPid());
							basMaterialLog.setQuantity(quantity);
							basMaterialLog.setSalePrice(basMaterial.getSalePrice());
							basMaterialLog.setSquare(basMaterial.getSquare());
							basMaterialLog.setSupplier(supplier);
							basMaterialLog.setTaxCode(basMaterial.getTaxCode());
							basMaterialLog.setUnitId(basMaterial.getUnitId());
							basMaterialLog.setUpdateBy(basMaterial.getUpdateBy());
							basMaterialLog.setUpdateTime(basMaterial.getUpdateTime());
							basMaterialLog.setViceQuantity(basMaterial.getViceQuantity());
							basMaterialLog.setWidth(basMaterial.getWidth());
							basMaterialLog.setRemark(remark);
							logList.add(basMaterialLog);
						}
					}
					this.saveBatch(logList);
				}else {
					throw new RuntimeException("未查找到物料信息");
				}
			}else {
				throw new RuntimeException("未查找到托盘信息");
			}
		}
		if(buffer!=null&&buffer.length()>0) {
			return Result.ok("扫入重复的物料码或托盘码："+buffer.toString()+"出现重复");
		}else {
			return Result.ok("记录成功");
		}
	}

	@Override
	public Result<?> queryQuantSum(BasMaterialLog basMaterialLog, HttpServletRequest req) {
		// TODO Auto-generated method stub
		QueryWrapper<BasMaterialLog> queryWrapper = QueryGenerator.initQueryWrapper(basMaterialLog, req.getParameterMap());
		List<BasMaterialLog> list = this.list(queryWrapper);
		BigDecimal sum = BigDecimal.ZERO;
		if(list!=null && list.size()>0) {
			for(BasMaterialLog log:list) {
				if(oConvertUtils.isNotEmpty(log.getQuantity())) {
					sum = sum.add(log.getQuantity());//累加计算数量
				}
			}
		}
		return Result.ok(sum);
	}

	@Override
	public Result<?> queryInventSum(BasMaterialLogVO vo) {
		// TODO Auto-generated method stub
		List<String> ids = Lists.newArrayList();
		if(!StringUtils.isBlank(vo.getCategoryId())) {
			LambdaQueryWrapper<BasMaterial> query = new LambdaQueryWrapper<>();
			query.eq(BasMaterial::getCategoryId, vo.getCategoryId());
			List<BasMaterial> list = this.materialService.list(query);
			ids.add(UUID.randomUUID().toString());
			if(null != list && list.size() > 0) {
				for (BasMaterial mate : list) {
					ids.add(mate.getId());
				}
				vo.setIds(ids);
			}
		}
		List<InventoryDTO> list = this.baseMapper.getInventorySum(vo);
		BigDecimal sum = BigDecimal.ZERO;
		if(list!=null && list.size()>0) {
			for(InventoryDTO stk:list) {
				if(oConvertUtils.isNotEmpty(stk.getQty())) {
					sum = sum.add(stk.getQty());//累加计算数量
				}
			}
		}
		return Result.ok(sum);
	}

	@Override
	public List<MaterialContrastDTO> queryDTOList(BasMaterialLogVO vo) {
		// TODO Auto-generated method stub
		//根据条件查询盘点物料信息
//		List<String> cateList = Lists.newArrayList();//分类id
		List<String> materialIds = Lists.newArrayList();//物料id
		LambdaQueryWrapper<BasMaterialLog> query = new LambdaQueryWrapper<>();
		query.eq(BasMaterialLog::getSheetId, vo.getSheetId());
		if(oConvertUtils.isNotEmpty(vo.getCategoryId())) {
			query.eq(BasMaterialLog::getCategoryId, vo.getCategoryId());
			List<BasMaterial> materialList = materialService.getByCategoryId(vo.getCategoryId());
			if(materialList!=null && materialList.size()>0) {
				for(BasMaterial bas:materialList) {
					materialIds.add(bas.getId());
				}
			}
		}
		List<BasMaterialLog> logList = this.list(query);
		Map<String,BigDecimal> logMap = Maps.newHashMap();//存放物料分类对应数量
		if(logList!=null && logList.size()>0) {
			for(BasMaterialLog log:logList) {
				if(logMap.get(log.getCategoryId())!=null) {
					String materialId = log.getMaterialId();
					StkInventory stk = stkInventoryService.getByMaterial(materialId);
					if(stk!=null && stk.getQty()!=null) {
						BigDecimal quant = logMap.get(log.getCategoryId()).add(stk.getQty());
						logMap.put(log.getCategoryId(), quant);
					}
				}else {
					if(log.getQuantity()!=null) {
						String materialId = log.getMaterialId();
						StkInventory stk = stkInventoryService.getByMaterial(materialId);
						if(stk!=null && stk.getQty()!=null) {
							logMap.put(log.getCategoryId(), stk.getQty());
						}
					}
				}
			}
		}
		vo.setIds(materialIds);
		List<MaterialContrastDTO> dtoList = materialLogMapper.getContrastDTOList(vo);
		if(dtoList!=null && dtoList.size()>0) {
			for(MaterialContrastDTO dto:dtoList) {
				if(logMap.get(dto.getCategoryId())!=null) {
					dto.setQuantitySum(logMap.get(dto.getCategoryId()));
				}else {
					dto.setQuantitySum(BigDecimal.ZERO);
				}
			}
		}
		//根据盘点数量与实时库存数量的差值进行排序，将这两个数不同的排到前面
		dtoList.sort(Comparator.comparing(MaterialContrastDTO::getQuantitySum).reversed());
		return dtoList;
	}

	@Override
	public boolean replaceQty(BasMaterialLog basMaterialLog) {
		// TODO Auto-generated method stub
		if(oConvertUtils.isEmpty(basMaterialLog.getSheetId())) {
			throw new JeecgBootException("未找到盘点单");
		}
		//查询某个盘点单所有盘点物料
		LambdaQueryWrapper<BasMaterialLog> query = new LambdaQueryWrapper<>();
		query.eq(BasMaterialLog::getSheetId, basMaterialLog.getSheetId());
		List<BasMaterialLog> logList = this.list(query);
		//记录物料id
		List<String> materialIdList = Lists.newArrayList();
		List<String> cateList = Lists.newArrayList();
		Map<String, BigDecimal> map = Maps.newHashMap();
		if(logList!=null && logList.size()>0) {
			for(BasMaterialLog log:logList) {
				materialIdList.add(log.getMaterialId());
				map.put(log.getMaterialId(), log.getQuantity());
				if(!cateList.contains(log.getCategoryId())) {
					cateList.add(log.getCategoryId());
				}
			}
			LambdaQueryWrapper<BasMaterial> queryWrapper = new LambdaQueryWrapper<>();
			queryWrapper.in(BasMaterial::getCategoryId, cateList);
			List<BasMaterial> materialList = materialService.list(queryWrapper);
			if(materialList!=null && materialList.size()>0) {
				for(BasMaterial bas:materialList) {
					materialIdList.add(bas.getId());
				}
			}
		}
		if(materialIdList!=null && materialIdList.size()>0) {
			//根据物料id列表查询实时库存里的数据信息
			LambdaQueryWrapper<StkInventory> queryWrapper = new LambdaQueryWrapper<>();
			queryWrapper.in(StkInventory::getMaterialId, materialIdList);
			queryWrapper.gt(StkInventory::getQty, BigDecimal.ZERO);
			List<StkInventory> stkList = stkInventoryService.list(queryWrapper);
			if(stkList!=null && stkList.size()>0) {
				for(StkInventory stk:stkList) {
					if(map.get(stk.getMaterialId())==null) {
						if(StringUtils.equals("1316197125803118594", stk.getWarehouseId()) 
								|| StringUtils.equals("1375347575181709313", stk.getWarehouseId())) {
							continue;
						}
						stk.setQty(BigDecimal.ZERO);
					}
				}
				return stkInventoryService.updateBatchById(stkList);
			}
		}
		return false;
	}

	@Override
	public IPage<InventoryDTO> getInventory(BasMaterialLogVO vo, Page<InventoryDTO> page) {
		// TODO Auto-generated method stub
		List<String> ids = Lists.newArrayList();
		if(!StringUtils.isBlank(vo.getCategoryId())) {
			LambdaQueryWrapper<BasMaterial> query = new LambdaQueryWrapper<>();
			query.eq(BasMaterial::getCategoryId, vo.getCategoryId());
			List<BasMaterial> list = this.materialService.list(query);
			ids.add(UUID.randomUUID().toString());
			if(null != list && list.size() > 0) {
				for (BasMaterial mate : list) {
					ids.add(mate.getId());
				}
				vo.setIds(ids);
			}
		}
		return this.baseMapper.getInventory(vo, page);
	}

}
